/***************************************************************************\
 * Copyright (C) by Keio University
 * Maths.hpp created in 10 2011.
 * Mail : fdesorbi@hvrl.ics.keio.ac.jp
 *
 * Maths.hpp is part of the HVRL Engine Library.
 *
 * The HVRL Engine Library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * The HVRL Engine Library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
\***************************************************************************/

#ifndef COMMON__MATHS_HPP__
#define COMMON__MATHS_HPP__

#include <climits>

namespace hvrl
{

static const double PI = 3.14159265358979323846;

static const double TWO_PI = 6.28318530717958647692;

static const double PI_TWO = 1.57079632679489661923;

static const double PI_FOUR = 0.78539816339744830962;

static const double DEG2RAD = 0.01745329251994329576;

static const double RAD2DEG = 57.2957795130823208767;

static const double GOLDEN_NUMBER = 1.61803398874989484820;

static inline double degToRad(const double& deg)
{
    return deg*DEG2RAD;
}

static inline double radToDeg(const double& rad)
{
    return rad*RAD2DEG;
}

static inline bool isPowerOfTwo(const unsigned int& x)
{
    return ( (x > 0) && ((x & (x - 1)) == 0) );
}

static inline unsigned int fastSqrtui(const unsigned int& value)
{
    unsigned int temp, g=0, b = 0x8000, bshft = 15;
    unsigned int val = value;
    do
    {
        if (val >= (temp = (((g << 1) + b)<<bshft--)))
        {
            g += b;
            val -= temp;
        }
    }
    while (b >>= 1);
    return g;
}

template<typename T>
static inline T getSign(const T& a)
{
    if(a==T(0))return a;
    return a>T(0)?T(1):T(-1);
}

template <typename T>
static inline T ceilPowerOfTwo(const T& n)
{
    int k = n;
    if(k==0) return 1;
    k--;
    for (unsigned int i=1; i<sizeof(int)*CHAR_BIT; i<<=1)
        k = k | k >> i;
    return k+1;
}

/**
  * \brief Find the highest power of two not more than a particular integer
  * \param n the upper limit
  * \return the highest power of two
  * \sa ceilPowerOfTwo
  */
template <typename T>
static inline T floorPowerOfTwo(const T& n)
{
    return ceilPowerOfTwo(n) >> 1;
}

}

#endif
